package com.example.excel.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.fastjson.JSON;
import com.example.excel.constant.Const;
import com.example.excel.data.CommonResponse;
import com.example.excel.data.LongRentCarDto;
import com.example.excel.data.LongRentCarFailedDto;
import com.example.excel.data.LongRentCarVo;
import com.example.excel.listener.LongRentCarListener;
import com.example.excel.util.EasyExcelUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * @author Aaron
 * @since 2021/7/14 11:22
 * <p>描述：</p>
 */
@RestController
@RequestMapping("/longRentCar")
public class LongRentCarController {
    private static final Logger LOGGER = LoggerFactory.getLogger(LongRentCarController.class);

    private static final Map<Integer, List<LongRentCarFailedDto>> FAILED_DATA_MAP = new HashMap<>();

    @RequestMapping("/excelTemplateDownload")
    public void excelTemplateDownload(HttpServletResponse response, @RequestBody LongRentCarVo longRentCarVo) {
        LOGGER.debug("longRentCarTemplateDownload 入参：{}", JSON.toJSONString(longRentCarVo));
        try {
            if (longRentCarVo.getIsIE() == 1) {
                LOGGER.debug("是 IE：{}", longRentCarVo.getIsIE());
            }
            List<LongRentCarDto> data = new ArrayList<>();
            data.add(LongRentCarDto.builder().parkName("示例勿删").sectionName("全场").carOwnerName("张三")
                    .carOwnerTel("13068889888").address("中岳大街").companyName("二大队").carNum("豫A12345")
                    .vehicleType("1").beginDateStr("2018-09-01").endDateStr("2022-07-30").fee("200").build());
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("长租车导入模板", "utf-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

            EasyExcel.write(response.getOutputStream(), LongRentCarFailedDto.class)
                    .autoCloseStream(Boolean.TRUE)
                    .excelType(ExcelTypeEnum.XLSX)
                    .withTemplate(ResourceUtils.getFile("classpath:templates/长租车导入模板.xlsx"))
                    .registerWriteHandler(EasyExcelUtil.defaultStyleStrategy())
                    .needHead(false)
                    .sheet()
                    .doWrite(data);
        } catch (Exception e) {
            LOGGER.error("导出异常：", e);
        }
    }

    @RequestMapping("/excelExport")
    public void excelExport(HttpServletResponse response, @RequestBody LongRentCarVo longRentCarVo) {
        LOGGER.debug("longRentCarExport 入参：{}", JSON.toJSONString(longRentCarVo));
        try {
            if (longRentCarVo.getIsIE() == 1) {
                LOGGER.debug("是 IE：{}", longRentCarVo.getIsIE());
            }

            List<LongRentCarDto> data = new ArrayList<>();
            data.add(LongRentCarDto.builder().parkName("Aaron_2.0测试").sectionName("全场").carOwnerName("张三")
                    .carOwnerTel("13068889889").address("中岳大街").companyName("二大队").carNum("豫RLY123").vehicleType("1")
                    .beginDateStr("2018-09-01").endDateStr("2022-07-30").fee("200").build());
            data.add(LongRentCarDto.builder().parkName("Aaron_3.0坐席").sectionName("外场").carOwnerName("李四")
                    .carOwnerTel("13068889888").address("中岳大街").companyName("二大队").carNum("豫RLY122")
                    .vehicleType("1").beginDateStr("2018-09-01").endDateStr("2022-07-30").fee("200").build());
            data.add(LongRentCarDto.builder().parkName("Aaron_3.0测试").sectionName("内场").carOwnerName("马六")
                    .carOwnerTel("13068889887").address("中岳大街").companyName("二大队").carNum("豫RLY121")
                    .vehicleType("1").beginDateStr("2018-09-01").endDateStr("2022-07-30").fee("200").build());

            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("长租车导出数据", "utf-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

            EasyExcel.write(response.getOutputStream(), LongRentCarFailedDto.class)
                    .autoCloseStream(Boolean.TRUE)
                    .excelType(ExcelTypeEnum.XLSX)
                    .withTemplate(ResourceUtils.getFile("classpath:templates/长租车导入模板.xlsx"))
                    .registerWriteHandler(EasyExcelUtil.defaultStyleStrategy())
                    .needHead(false)
                    .sheet()
                    .doWrite(data);
        } catch (Exception e) {
            LOGGER.error("导出异常：", e);
        }
    }

    @RequestMapping("/excelImport")
    public CommonResponse<?> excelImport(@RequestParam("file") MultipartFile file, LongRentCarVo longRentCarVo) {
        try {
            LOGGER.debug("longRentCarImport 入参：{}", JSON.toJSONString(longRentCarVo));

            List<LongRentCarFailedDto> importFailedList = new ArrayList<>();
            List<LongRentCarDto> importTotalData = new ArrayList<>();
            Function<LongRentCarDto, String> checkFunction = this::doCheck;
            EasyExcel.read(file.getInputStream(), LongRentCarDto.class,
                    new LongRentCarListener(importTotalData, importFailedList, checkFunction))
                    .headRowNumber(3)
                    .sheet()
                    .doRead();

            if (!CollectionUtils.isEmpty(importFailedList)) {
                LOGGER.debug("导入失败数据：{}", JSON.toJSONString(importFailedList));
                FAILED_DATA_MAP.put(longRentCarVo.getParkId(), importFailedList);
                return CommonResponse.success(importFailedList.size(), "导入失败数据：" + importFailedList.size() + "条");
            }

            return CommonResponse.success(0, "导入成功");
        } catch (Exception e) {
            LOGGER.error("导入异常：", e);
            return CommonResponse.error("长租车导入异常");
        }
    }

    @RequestMapping("/failedExcelExport")
    public void failedExcelExport(HttpServletResponse response, @RequestBody LongRentCarVo longRentCarVo) {
        LOGGER.debug("failedDataDownload 入参：{}", JSON.toJSONString(longRentCarVo));
        try {
            if (longRentCarVo.getIsIE() == 1) {
                LOGGER.debug("是 IE：{}", longRentCarVo.getIsIE());
            }
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("长租车导入失败数据", "utf-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            List<LongRentCarFailedDto> importFailedList = FAILED_DATA_MAP.get(longRentCarVo.getParkId());
            LOGGER.debug("导入失败数据：{}", JSON.toJSONString(importFailedList));

            EasyExcel.write(response.getOutputStream(), LongRentCarFailedDto.class)
                    .autoCloseStream(Boolean.TRUE)
                    .excelType(ExcelTypeEnum.XLSX)
                    .withTemplate(ResourceUtils.getFile("classpath:templates/长租车导入失败模板.xlsx"))
                    .registerWriteHandler(EasyExcelUtil.defaultStyleStrategy())
                    .needHead(false)
                    .sheet()
                    .doWrite(importFailedList);
        } catch (Exception e) {
            LOGGER.error("导出异常：", e);
        }
    }

    private String doCheck(LongRentCarDto longRentCar) {
        if (StringUtils.isBlank(longRentCar.getSectionName()) || notExist(longRentCar.getSectionName())) {
            return "区域不存在";
        }
        if (StringUtils.isNotBlank(longRentCar.getCarOwnerName()) && longRentCar.getCarOwnerName().length() > Const.Number.THIRTY_TOW) {
            return "用户名超过32位";
        }
        if (StringUtils.isNotBlank(longRentCar.getCarOwnerTel()) && !longRentCar.getCarOwnerTel().matches(Const.Regex.TEL)) {
            return "手机号码格式有误";
        }
        if (StringUtils.isNotBlank(longRentCar.getAddress()) && longRentCar.getAddress().length() > Const.Number.HUNDRED) {
            return "地址超出100个字符";
        }
        if (StringUtils.isNotBlank(longRentCar.getCompanyName()) && longRentCar.getCompanyName().length() > Const.Number.UNSIGNED_CHAR) {
            return "地址超出255个字符";
        }

        String carNumRule = Const.Regex.CAR_NUM;
        if (StringUtils.isBlank(longRentCar.getCarNum())) {
            return "车牌号不能为空";
        }
        String[] carNums = longRentCar.getCarNum().split(Const.Regex.NEWLINE);
        for (String carNum : carNums) {
            if (!carNum.matches(carNumRule)) {
                return "车牌格式错误";
            }
        }

        if (StringUtils.isBlank(longRentCar.getVehicleType())) {
            return "车型不能为空";
        }
        String[] vehicleTypes = longRentCar.getVehicleType().split(Const.Regex.NEWLINE);
        for (String vehicleType : vehicleTypes) {
            if (!vehicleType.matches(Const.Regex.CAR_TYPE)) {
                return "车型格式错误";
            }
        }
        if (carNums.length != vehicleTypes.length) {
            return "车牌和车型数量不匹配";
        }
        if (StringUtils.isBlank(longRentCar.getBeginDateStr())) {
            return "生效日期不能为空";
        }
        String[] beginDataStrs = longRentCar.getBeginDateStr().split(Const.Regex.NEWLINE);
        for (String beginDataStr : beginDataStrs) {
            if (!beginDataStr.matches(Const.Regex.DATEFORMAT)) {
                return "生效日期格式错误";
            }
        }
        if (StringUtils.isBlank(longRentCar.getEndDateStr())) {
            return "失效日期不能为空";
        }
        String[] endDataStrs = longRentCar.getEndDateStr().split(Const.Regex.NEWLINE);
        for (String endDataStr : endDataStrs) {
            if (!endDataStr.matches(Const.Regex.DATEFORMAT)) {
                return "失效日期格式错误";
            }
        }
        if (beginDataStrs.length != endDataStrs.length) {
            return "生效日期和失效日期数量不匹配";
        }

        return null;
    }

    private boolean notExist(String sectionName) {
        List<String> sectionList = new ArrayList<>(4);
        sectionList.add("aa");

        return !"全场".equals(sectionName) && !sectionList.contains(sectionName);
    }

}
